package com.baijia.jigou.util;

import java.io.IOException;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.baijia.util.ServiceLocator;
import com.google.code.yanf4j.core.impl.StandardSocketOption;

import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.XMemcachedClientBuilder;
import net.rubyeye.xmemcached.exception.MemcachedException;

public class OrgMemcachedUtil {

    private static final int DEF_EXP = 3600;
    private static JiGouMemcachedClient memcachedClient;
    private static final Logger logger = LoggerFactory.getLogger(OrgMemcachedUtil.class);
    private static Lock lock = new ReentrantLock();

    public static boolean delete(String arg0) throws TimeoutException, InterruptedException, MemcachedException {
        if (StringUtils.isBlank(arg0)) {
            return false;
        }
        return getClient().delete(arg0);
    }

    public static <T> T get(String arg0) throws TimeoutException, InterruptedException, MemcachedException {
        return getClient().get(arg0);
    }
    
    public static <T> T getBySessionId(String sessionId) throws TimeoutException, InterruptedException, MemcachedException {
        return getClient().get("JIGOU_"+sessionId);
    }
    
    public static boolean set(String arg0, int arg1, Object arg2)
        throws TimeoutException, InterruptedException, MemcachedException {
        return getClient().set(arg0, arg1, arg2);
    }

    public static boolean set(String arg0, Object arg1)
        throws TimeoutException, InterruptedException, MemcachedException {
        return getClient().set(arg0, DEF_EXP, arg1);
    }

    private static JiGouMemcachedClient getClient() {

        if (memcachedClient == null) {
            lock.lock();
            if (memcachedClient == null) {
                XMemcachedClientBuilder builder1 =
                    (XMemcachedClientBuilder) ServiceLocator.getBean("memcachedClientBuilder");
                builder1.getSocketOptions().put(StandardSocketOption.TCP_NODELAY, Boolean.TRUE);
                XMemcachedClientBuilder builder2 =
                    (XMemcachedClientBuilder) ServiceLocator.getBean("memcachedClientBuilder2");
                builder2.getSocketOptions().put(StandardSocketOption.TCP_NODELAY, Boolean.TRUE);
                try {
                    MemcachedClient memcachedClient1 = builder1.build();
                    MemcachedClient memcachedClient2 = builder2.build();
                    memcachedClient = new JiGouMemcachedClient(memcachedClient2, memcachedClient1);
                } catch (IOException e) {
                    logger.error("memcache getClient error", e);
                } finally {
                    lock.unlock();
                }
            }
        }
        return memcachedClient;
    }
    
    public void shutdown() {
        MemcachedClient[] memcachedClients = memcachedClient.getMemcachedClients();
        if(ArrayUtils.isNotEmpty(memcachedClients)){
            for(MemcachedClient client : memcachedClients){
                if(client!=null && !client.isShutdown()){
                    try {
                        client.shutdown();
                    } catch (IOException e) {
                        logger.error("shutdown MemcachedClient error!client:"+client, e);
                    }
                }
            }
        }
    }
    
    static class JiGouMemcachedClient {

        private MemcachedClient[] memcachedClients;

        public JiGouMemcachedClient(MemcachedClient...clients) {
            if (clients != null && clients.length > 0) {
                memcachedClients = new MemcachedClient[clients.length];
                int index = 0;
                for (MemcachedClient client : clients) {
                    memcachedClients[index++] = client;
                }
            }
        }

        public boolean delete(String arg0) throws TimeoutException, InterruptedException, MemcachedException {
            if (StringUtils.isBlank(arg0)) {
                return false;
            }

            for (MemcachedClient client : memcachedClients) {
                client.delete(arg0);
            }
            return true;
        }

        public <T> T get(String arg0) throws TimeoutException, InterruptedException, MemcachedException {

            int count = 0;
            for (MemcachedClient client : memcachedClients) {
                count++;
                try {
                    T t = client.get(arg0);
                    if (t != null) {
                        return t;
                    }

                } catch (TimeoutException | InterruptedException | MemcachedException e) {
                    if (count >= memcachedClients.length) {
                        throw e;
                    }
                }
            }

            return null;
        }

        public boolean set(String arg0, int arg1, Object arg2)
            throws TimeoutException, InterruptedException, MemcachedException {
            boolean isSuccess = false;
            for (MemcachedClient client : memcachedClients) {
                try {
                    if (client.set(arg0, arg1, arg2)) {
                        isSuccess = true;
                    }

                } catch (TimeoutException | InterruptedException | MemcachedException e) {
                    if (!isSuccess) {
                        throw e;
                    }
                }
            }
            return isSuccess;
        }

        public boolean set(String arg0, Object arg1) throws TimeoutException, InterruptedException, MemcachedException {

            boolean isSuccess = false;
            for (MemcachedClient client : memcachedClients) {
                try {
                    if (client.set(arg0, DEF_EXP, arg1)) {
                        isSuccess = true;
                    }
                } catch (TimeoutException | InterruptedException | MemcachedException e) {
                    if (!isSuccess) {
                        throw e;
                    }
                }
            }
            return isSuccess;
        }
        
        public MemcachedClient[] getMemcachedClients(){
            return memcachedClients;
        }
    }

}
